/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package locusts.lib;

import java.awt.Shape;
import java.awt.geom.GeneralPath;
import java.util.Random;

/**
 * Utility class to construct complex shapes.
 * 
 * @author hamish
 */
public final class Shapes {

    private static final Random RAND = new Random();

    private Shapes() {
    }

    /**
     * Equilateral
     */
    public static Shape createTriangle(double x, double y,
            double length) {
        return createTriangle(x, y, length, length);

    }

    /**
     * Isosceles
     */
    public static Shape createTriangle(double x, double y, double w,
            double h) {
        final double opp = Math.sqrt(h * h - w * w / 4);
        return createTriangle(
                x - w / 2d, y + opp / 2d,
                0, y - opp / 2d,
                x + w / 2d, y + opp / 2d);
    }

    /**
     * Scalene
     */
    public static GeneralPath createTriangle(double x1, double y1,
            double x2,
            double y2, double x3, double y3) {

        final GeneralPath p = new GeneralPath();
        p.moveTo((float) x1, (float) y1);
        p.lineTo((float) x2, (float) y2);
        p.lineTo((float) x3, (float) y3);
        p.closePath();
        p.getPathIterator(null, 1);
        return p;
    }

    public static Shape createArrowBox(double x, double y, double w,
            double h) {

        final float x1 = (float) (x);
        final float x2 = (float) (x + w * .25);
        final float x3 = (float) (x + w * .40);
        final float x4 = (float) (x + w * .5);
        final float x5 = (float) (x + w * .6);
        final float x6 = (float) (x + w * .75);
        final float x7 = (float) (x + w);

        final float y1 = (float) (y);
        final float y2 = (float) (y + h * .5);
        final float y3 = (float) (y + h * .75);
        final float y4 = (float) (y + h);

        final GeneralPath shape
                = new GeneralPath(GeneralPath.WIND_NON_ZERO, 12);
        shape.moveTo(x1, y1);
        shape.lineTo(x1, y2);
        shape.lineTo(x3, y2);
        shape.lineTo(x3, y3);
        shape.lineTo(x2, y3);
        shape.lineTo(x4, y4);
        shape.lineTo(x6, y3);
        shape.lineTo(x5, y3);
        shape.lineTo(x5, y2);
        shape.lineTo(x7, y2);
        shape.lineTo(x7, y1);
        shape.closePath();

        return shape;
    }

    public static Shape createJaggedEllipse(double x, double y,
            double w, double h, int n) {

        final GeneralPath p = new GeneralPath();
        p.moveTo((float) (w / 2), 0);
        for (int i = 0; i < n; i++) {
            {
                final double theta = (Math.PI * 2d * i) / n + (RAND.
                        nextDouble() * Math.PI / n);

                final double d = 0.5;
                final double x0 = x + w * d * Math.cos(theta);
                final double y0 = y + h * d * Math.sin(theta);
                p.lineTo((float) x0, (float) y0);
            }
            {
                final double theta =
                        (Math.PI * 2d * (i + 0.3333)) / n + (RAND.
                        nextDouble() * Math.PI / n);
                final double d = 0.1 + RAND.nextDouble() * .4;
                final double x0 = x + w * d * Math.cos(theta);
                final double y0 = y + h * d * Math.sin(theta);
                p.lineTo((float) x0, (float) y0);
            }
            {
                final double theta = (Math.PI * 2d * (i + 0.66666)) /
                        n + (RAND.nextDouble() * Math.PI / n);
                final double d = 0.5;
                final double x0 = x + w * d * Math.cos(theta);
                final double y0 = y + h * d * Math.sin(theta);
                p.lineTo((float) x0, (float) y0);
            }
        }
        p.closePath();
        
        return p;
    }

    public static GeneralPath createSpaceship(double x, double y, double w,
            double h) {
        final double opp = Math.sqrt(h * h - w * w / 4);

        final float x0 = (float) (x - w / 2d);
        final float x1 = 0;
        final float x2 = (float) (x + w / 2d);

        final float y0 = (float) (y - opp / 2d);
        final float y1 = (float) (y - opp / 3d);
        final float y2 = (float) (y + opp / 2d);

        final GeneralPath p = new GeneralPath();
        p.moveTo(x1, y2);
        p.lineTo(x2, y0);
        //p.lineTo(x0, y0);
        p.curveTo((x2 + x1) / 2, y1, (x1 + x0) / 2, y1, x0, y0);
        p.closePath();
        return p;
    }

    public static Shape createSpaceshipMoving(double x, double y,
            double w,double h) {
        final GeneralPath p = createSpaceship(x, y, w, h);
        final double opp = Math.sqrt(h * h - w * w / 4);
        final float x0 = (float) (x - w / 4d);
        final float x1 = 0;
        final float x2 = (float) (x + w / 4d);
        final float ya = (float) (y - opp);
        final float y0 = (float) (y - opp * 0.6d);
        final float y1 = (float) (y - opp * 0.4d);
        p.moveTo(x0, y0);
        p.lineTo(x1, ya);
        p.lineTo(x2, y0);
        p.curveTo((x2 + x1) / 2, y1, (x1 + x0) / 2, y1, x0, y0);
        p.closePath();
        return p;
    }

    public static Shape createAlien(double x, double y, double w,
            double h) {
        final GeneralPath p = new GeneralPath();
        final double x0 = x - w / 2d;
        final double x1 = x - w / 6d;
        final double x2 = x - w / 10d;
        final double x3 = x + w / 10d;
        final double x4 = x + w / 6d;
        final double x5 = x + w / 2d;
        final double y3 = y - h / 2d;
        final double y2 = y - h / 6d;
        final double y1 = y + h / 6d;
        final double y0 = y + h / 2d;

        p.moveTo((float) x0, (float) y1);
        p.lineTo((float) x1, (float) y2);
        p.lineTo((float) x2, (float) y3);
        p.lineTo((float) x3, (float) y3);
        p.lineTo((float) x4, (float) y2);
        p.lineTo((float) x5, (float) y1);
        p.lineTo((float) x4, (float) y0);
        p.lineTo((float) x2, (float) y0);
        p.closePath();
//        p.moveTo((float) x0, (float) y1);
//        p.lineTo((float) x5, (float) y1);
//        p.moveTo((float) x2, (float) y2);
//        p.lineTo((float) x4, (float) y2);

        return p;
    }
}
